#include <stdint.h>

#include "config.h"
#include "stdio.h"
#include "stdlib.h"

static unsigned char rgb[SCREEN_BUFFER_HEIGHT][SCREEN_BUFFER_WIDTH][3];  // y,x, RGB
static void screen_buffer_copy();

unsigned char *screen_buffer_get_data() {
  screen_buffer_copy();
  return (unsigned char *)&rgb;
}

#if SCREEN_BUFFER_COLOR_DEPTH == 1
uint8_t frame_buffer[SCREEN_BUFFER_HEIGHT / 8][SCREEN_BUFFER_WIDTH];
static void screen_buffer_setrgb(uint32_t row, uint32_t col, uint8_t v) {
  if (v) {
    rgb[row][col][0] = SCREEN_BUFFER_COLOR_FRONT & 0xff;
    rgb[row][col][1] = (SCREEN_BUFFER_COLOR_FRONT >> 8) & 0xff;
    rgb[row][col][2] = (SCREEN_BUFFER_COLOR_FRONT >> 16) & 0xff;
  } else {
    rgb[row][col][0] = SCREEN_BUFFER_COLOR_BACKGROUD & 0xff;
    rgb[row][col][1] = (SCREEN_BUFFER_COLOR_BACKGROUD >> 8) & 0xff;
    rgb[row][col][2] = (SCREEN_BUFFER_COLOR_BACKGROUD >> 16) & 0xff;
  }
}
static void screen_buffer_copy() {
  uint32_t row_bytes = SCREEN_BUFFER_HEIGHT / 8;

  for (uint32_t row = 0; row < row_bytes; row++) {
    for (uint32_t col = 0; col < SCREEN_BUFFER_WIDTH; col++) {
#if SCREEN_BUFFER_BIT_LSB
      for (int i = 0; i < 8; i++) {
        screen_buffer_setrgb(row * 8 + i, col, frame_buffer[row][col] & (1 << i));
      }
#else
      for (int i = 0; i < 8; i++) {
        screen_buffer_setrgb(row * 8 + i, col, frame_buffer[row][col] & (1 << (7 - i)));
      }

#endif /* SCREEN_BUFFER_BIT_LSB */
    }
  }
}
#elif SCREEN_BUFFER_COLOR_DEPTH == 16
uint8_t frame_buffer[SCREEN_BUFFER_HEIGHT][SCREEN_BUFFER_WIDTH][2];
static void screen_buffer_copy() {
  for (uint32_t r = 0; r < SCREEN_BUFFER_HEIGHT; r++) {
    for (uint32_t c = 0; c < SCREEN_BUFFER_WIDTH; c++) {
      rgb[r][c][0] = (frame_buffer[r][c][1] & 0xF8) | 0x07;
      rgb[r][c][1] = (frame_buffer[r][c][1] << 5) + ((frame_buffer[r][c][0] & 0xE0) >> 3) + 0x03;
      rgb[r][c][2] = (frame_buffer[r][c][0] << 3) + 0x07;
    }
  }
}
#elif SCREEN_BUFFER_COLOR_DEPTH == 24
uint8_t frame_buffer[SCREEN_BUFFER_HEIGHT][SCREEN_BUFFER_WIDTH][3];
static void screen_buffer_copy() { memcpy(rgb, frame_buffer, sizeof(frame_buffer)); }
#elif
#error "SCREEN_BUFFER_COLOR_DEPTH ERROR, should be 1,8,16,24"
#endif /* SCREEN_BUFFER_COLOR_DEPTH */

void screen_buffer_init() {}